package com.ocm.tourism.web;

import com.ocm.tourism.core.domain.FileInfo;
import com.ocm.tourism.core.domain.Participant;
import com.ocm.tourism.core.domain.RoleType;
import com.ocm.tourism.core.domain.SecurityRole;
import com.ocm.tourism.core.model.ParticipantCriteria;
import com.ocm.tourism.core.model.UserInfo;
import com.ocm.tourism.core.service.BusinessService;
import com.ocm.tourism.core.service.ParticipantService;
import com.ocm.tourism.core.util.UserUtil;
import com.ocm.tourism.web.util.FileInfoUtil;
import com.ocm.tourism.web.validator.FileValidator;
import com.ocm.tourism.web.validator.ParticipantValidator;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import org.springframework.web.util.UriUtils;
import org.springframework.web.util.WebUtils;

@RequestMapping("/participant")
@Controller
@SessionAttributes("ParticipantController.ParticipantCriteria")
public class ParticipantController {

   private static final String SESSION_ParticipantCriteria = "ParticipantController.ParticipantCriteria";

   @Autowired
   ParticipantService participantService;

   @Autowired
   BusinessService businessService;

   @Autowired
   FileValidator fileValidator;

   @Autowired
   ParticipantValidator participantValidator;

   @Autowired
   FileInfoUtil fileInfoUtil;

   @RequestMapping(method = RequestMethod.POST, produces = "text/html")
   public String create(@Valid Participant participant,
         @RequestParam("fileData") CommonsMultipartFile commonsMultipartFile, BindingResult bindingResult,
         Model uiModel, HttpServletRequest httpServletRequest) throws Exception {
      participantValidator.validateParticipant(participant, bindingResult);
      fileValidator.validate(commonsMultipartFile, bindingResult);
      if (bindingResult.hasErrors()) {
         populateEditForm(uiModel, participant);
         return "participant/create";
      }
      uiModel.asMap().clear();
      if (commonsMultipartFile.getSize() > 0) {
         String uploadDir = httpServletRequest.getSession().getServletContext().getInitParameter("uploadDir");
         String folderPath = fileInfoUtil.createContainer(uploadDir);
         FileInfo fileInfo = fileInfoUtil.writeFile(commonsMultipartFile, uploadDir, folderPath);
         participant.setAvatar(fileInfo);
      } else {
         Long participantId = participant.getId(); 
         if (participantId != null && participantId > 0 ){
            Participant actual = this.participantService.findParticipant(participant.getId());
            participant.setAvatar(actual.getAvatar());
         }
      }
      participant.setActive(true);
      SecurityRole securityRole = new SecurityRole();
      securityRole.setRoleType(RoleType.ROLE_USER);
      participant.addSecuirtyRoles(securityRole);
      if ("tayninhadmin".equalsIgnoreCase(participant.getUsername())){
         securityRole = new SecurityRole();
         securityRole.setRoleType(RoleType.ROLE_ADMIN);
         participant.addSecuirtyRoles(securityRole);
      }
      participantService.saveParticipant(participant);
      return "redirect:/participant/success";
   }

   @RequestMapping(value = "/success", method = RequestMethod.GET)
   public String informSuccess(Model uiModel) {
      return "participant/success";
   }

   @RequestMapping(value = "/create", method = RequestMethod.GET)
   public String createForm(Model uiModel) {
      populateEditForm(uiModel, new Participant());
      return "participant/create";
   }

   @RequestMapping(value = "/update", method = RequestMethod.GET)
   public String updateCurrentUserLogin(Model uiModel) {
      UserInfo currentuser = UserUtil.getAuthenticated();
      Participant participant = this.participantService.findParticipant(currentuser.getParticipantId());
      populateEditForm(uiModel, participant);
      return "participant/update";
   }

   /*@RequestMapping(value = "/{id}", produces = "text/html")
   public String show(@PathVariable("id") Long id, Model uiModel) {
      uiModel.addAttribute("participant", participantService.findParticipant(id));
      uiModel.addAttribute("itemId", id);
      return "participant/show";
   }*/

   /*@RequestMapping(produces = "text/html")
   public String list(@RequestParam(value = "page", required = false) Integer page,
         @RequestParam(value = "size", required = false) Integer size, Model uiModel) {
      if (page != null || size != null) {
         int sizeNo = size == null ? 10 : size.intValue();
         final int firstResult = page == null ? 0 : (page.intValue() - 1) * sizeNo;
         uiModel.addAttribute("participants", participantService.findParticipants(firstResult, sizeNo));
         float nrOfPages = (float) participantService.countAllParticipants() / sizeNo;
         uiModel.addAttribute("maxPages", (int) ((nrOfPages > (int) nrOfPages || nrOfPages == 0.0) ? nrOfPages + 1
               : nrOfPages));
      } else {
         uiModel.addAttribute("participants", participantService.findParticipants(0, 50));
      }
      return "participant/list";
   }*/

   @RequestMapping(value = "/{id}/update", method = RequestMethod.GET)
   public String updateForm(@PathVariable("id") Long id, Model uiModel) {
      participantValidator.validatePermission(id);
      populateEditForm(uiModel, participantService.findParticipant(id));
      return "participant/update";
   }

   @RequestMapping(value = "/management/{id}/lock", method = RequestMethod.PUT)
   public String lock(@PathVariable("id") Long id, Model uiModel) {
      Participant participant = participantService.findParticipant(id);
      participant.setActive(false);
      this.participantService.saveParticipant(participant);
      uiModel.asMap().clear();
      return "redirect:/participant/management/search/advantage/back";
   }

   @RequestMapping(value = "/management/{id}/unlock", method = RequestMethod.PUT)
   public String unlock(@PathVariable("id") Long id, Model uiModel) {
      Participant participant = participantService.findParticipant(id);
      participant.setActive(true);
      this.participantService.saveParticipant(participant);
      uiModel.asMap().clear();
      return "redirect:/participant/management/search/advantage/back";
   }

   @RequestMapping(value = "/management/{id}", method = RequestMethod.DELETE, produces = "text/html")
   public String delete(@PathVariable("id") Long id, @RequestParam(value = "page", required = false) Integer page,
         @RequestParam(value = "size", required = false) Integer size, Model uiModel) {
      Participant participant = participantService.findParticipant(id);
      participantService.deleteParticipant(participant);
      uiModel.asMap().clear();
      uiModel.addAttribute("page", (page == null) ? "1" : page.toString());
      uiModel.addAttribute("size", (size == null) ? "10" : size.toString());
      return "redirect:/participant";
   }

   @RequestMapping(value = "/management/create", method = RequestMethod.GET)
   public String managementCreateForm(Model uiModel) {
      populateEditForm(uiModel, new Participant());
      return "participant/create";
   }
   
   @RequestMapping(value = "/management", method = RequestMethod.GET)
   public String list(Model uiModel) {
      uiModel.addAttribute("participants", new ArrayList<Participant>());
      uiModel.addAttribute("participant", new ParticipantCriteria());
      return "participant/management";
   }

   @RequestMapping(value="/management/search/advantage/back",method = RequestMethod.GET)
   public String searchAdvantage(Model uiModel){
      ParticipantCriteria participantCriteria = null; 
      if (uiModel.containsAttribute(SESSION_ParticipantCriteria)){
         participantCriteria = (ParticipantCriteria) uiModel.asMap().get(SESSION_ParticipantCriteria);
      }
      participantCriteria = participantCriteria == null ? new ParticipantCriteria() : participantCriteria;
      String returnStr = searchParticipant(participantCriteria, uiModel); 
      return returnStr;
   }

   @RequestMapping(value="/management/search/advantage",method = RequestMethod.POST)
   public String searchAdvantage(ParticipantCriteria participantCriteria, Model uiModel){
      uiModel.addAttribute(SESSION_ParticipantCriteria, participantCriteria);
      String returnStr = searchParticipant(participantCriteria, uiModel); 
      return returnStr;
   }

   @RequestMapping(value = "/management/{id}", produces = "text/html")
   public String showManagement(@PathVariable("id") Long id, Model uiModel) {
      uiModel.addAttribute("participant", participantService.findParticipant(id));
      uiModel.addAttribute("itemId", id);
      return "participant/show";
   }

   private String searchParticipant(ParticipantCriteria participantCriteria, Model uiModel){
      List<Participant> participants = this.participantService.findParticipants(participantCriteria.fill(), 0, 50);
      uiModel.addAttribute("participant", new ParticipantCriteria());
      uiModel.addAttribute("participants", participants);
      return "participant/management";
   }
   
   void populateEditForm(Model uiModel, Participant participant) {
      uiModel.addAttribute("participant", participant);
   }

   String encodeUrlPathSegment(String pathSegment, HttpServletRequest httpServletRequest) {
      String enc = httpServletRequest.getCharacterEncoding();
      if (enc == null) {
         enc = WebUtils.DEFAULT_CHARACTER_ENCODING;
      }
      try {
         pathSegment = UriUtils.encodePathSegment(pathSegment, enc);
      } catch (UnsupportedEncodingException uee) {
      }
      return pathSegment;
   }
}
